#include "worker_mgr.h"
#include "worker.h"
#include "list.h"
/* built-in worker type */
#include "dbworker.h"
#include "holicworker.h"

#include <malloc.h>
#include <string.h>
#include <assert.h>

C_CODE_BEGIN
struct worker_mgr {
	struct list* creator;
};

struct wmgr_ele{
	worker_creator creator;
	const char* name;
};

EXPORT_FUNC struct worker_mgr* worker_mgr_create() {
	struct worker_mgr* wm = malloc( sizeof( struct worker_mgr) );
	wm->creator = list_create( sizeof( struct wmgr_ele ) , 4 );
	/* initialize all the worker creator */
	_dbworker_register( wm );
	_holicworker_register(wm);
	return wm;
}


static void _destroy_name( void*obj , void* others ) {
	struct wmgr_ele* cr= (struct wmgr_ele*)(obj);
	free((void*)cr->name);
}

EXPORT_FUNC void worker_mgr_destroy( struct worker_mgr* mgr) {
	list_foreach((mgr->creator),_destroy_name,NULL);
	list_destroy((mgr->creator));
	free(mgr);
}


struct find {
	const char* name;
	struct wmgr_ele* obj;
};


static bool _find_creator( void* obj,void* others ) {
	struct wmgr_ele *tc = (struct wmgr_ele*)(obj);
	struct find* f = (struct find*)(others);
	if( strcmp(f->name , tc->name ) == 0 ) {
		f->obj = tc;
		return false;
	}
	return true;
}

#ifndef NDEBUG

static bool _check_creator_valid( struct worker_mgr* mgr ,const char* name ) {
	struct find f;
	f.name = name;
	f.obj = NULL;
	list_until((mgr->creator) , _find_creator , &f );
	return f.obj == NULL ;
}

#endif

EXPORT_FUNC void worker_mgr_register( struct worker_mgr* mgr, const char* name, worker_creator create ) {
	struct wmgr_ele tc;
	assert( _check_creator_valid(mgr,name) );
	tc.creator = create;
	tc.name = malloc( strlen(name) + 1 );
	strcpy( (char*)tc.name , name );
	list_push_back( (mgr->creator) , &tc );
} 

EXPORT_FUNC struct worker* worker_mgr_spawn_worker( struct worker_mgr * mgr, const char* worker_type , const char* thread_name , bool detach ) {
	struct find f;
	f.name = worker_type;
	f.obj = NULL;
	list_until((mgr->creator) , _find_creator , &f );
	return f.obj == NULL ? NULL : f.obj->creator( thread_name ,detach );
}

EXPORT_FUNC void worker_mgr_unregister( struct worker_mgr* mgr, const char* name ) {
	struct find f;
	f.name = name;
	f.obj = NULL;
	list_until((mgr->creator) , _find_creator , &f );
	if( f.obj ) {
		list_erase( mgr->creator , f.obj );
	}
}

C_CODE_END

